﻿<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:sys="javascript:Sys"
  xmlns:watermark="javascript:Sys.Extended.UI.TextBoxWatermarkBehavior"
  xmlns:maskededit="javascript:Sys.Extended.UI.MaskedEditBehavior"
  xmlns:ajax="urn:AjaxExtensions"
  xmlns:childAction="urn:ChildActionExtensions"
  xmlns:link="urn:LinkExtensions"
  xmlns:mvc="urn:HtmlHelper"
  xmlns:validation="urn:ValidationExtensions"
  xmlns:renderPartial="urn:RenderPartialExtensions"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  xmlns:xs="urn:dummy"
  xmlns:output="urn:output"
  xmlns:urlHelper="urn:UrlHelperExtensions"
  xmlns:form="urn:FormExtensions"
                xmlns:d="urn:atdw-com:data:v1"
  exclude-result-prefixes="msxsl sys watermark maskededit"
                  xmlns:eval="urn:eval">

  <!-- alias xs prefix -->
  <xsl:namespace-alias result-prefix="xsl" stylesheet-prefix="xs" />

  <!-- output style for Rendering Xslt [TODO: maybe this should be method="xml"] -->
  <xsl:output method="xml" indent="no" omit-xml-declaration="no" cdata-section-elements="script"  />
  <xsl:key name="isstatic" match="node()[count(namespace::*) = count(namespace::*[. = ../../namespace::*]) and (local-name(.)!='' or normalize-space(.)!='') and namespace-uri(.) != 'http://www.w3.org/1999/XSL/Transform' and namespace-uri((* | text()[normalize-space(.)!=''])[1]) != 'http://www.w3.org/1999/XSL/Transform']" use="generate-id(.)" />
  <xsl:key name="isdynamic" match="*[count(namespace::*) != count(namespace::*[. = ../../namespace::*]) or namespace-uri(.) = 'http://www.w3.org/1999/XSL/Transform' or namespace-uri((* | text()[normalize-space(.)!=''])[1]) = 'http://www.w3.org/1999/XSL/Transform']" use="generate-id(.)" />

  <!-- include external templates, as xslt -->
  <xsl:include href="~/Views/Templates.xslt" />
  <xsl:include href="~/Views/DocTypes.xslt" />

  <!-- params -->
  <xsl:param name="indent" select="'yes'" />
  <xsl:param name="stripSpace" select="''" />

  <!-- variables -->
  <xsl:variable name="apos">
    <xsl:text>'</xsl:text>
  </xsl:variable>

  <!-- define resource set [TODO: Configured and/or defined/overridden at runtime??] -->
  <xsl:variable name="resources" select="document('~/Views/Resources.xml')/root" />
  <xsl:key name="resource_key" match="root/data/value/text()" use="../../@name" />

  <!-- template::root - root template -->
  <xsl:template match="/">
    <xsl:variable name="cache" select="false()" />
    <xsl:choose>
      <xsl:when test="$cache">
        <xsl:variable name="test">
          <xsl:call-template name="generate" />
        </xsl:variable>
        <xsl:call-template name="process">
          <xsl:with-param name="data" select="msxsl:node-set($test)" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="generate" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="generate">
    <xs:stylesheet version="1.0" exclude-result-prefixes="ajax childAction link mvc renderPartial urlHelper eval">
      <!-- add extension namespaces to the stylesheet tag -->

      <!-- remove output: prefixes -->
      <xs:namespace-alias result-prefix="#default" stylesheet-prefix="output" />
      <!-- set output style -->
      <xs:output method="html" indent="{$indent}" omit-xml-declaration="yes" cdata-section-elements="script">
        <!-- define doctype, if specified -->
        <xsl:if test="/*[@doctype]">
          <xsl:call-template name="outputDocType">
            <xsl:with-param name="doctype" select="*/@doctype" />
          </xsl:call-template>
        </xsl:if>
      </xs:output>
      <!-- remove whitespace -->
      <xsl:if test="$stripSpace">
        <xs:strip-space elements="{$stripSpace}" />
      </xsl:if>
      <!-- define parameters -->
      <xsl:for-each select="/*/param">
        <xs:param name="{@name}">
          <xsl:if test="@select">
            <xsl:attribute name="select">
              <xsl:value-of select="@select" />
            </xsl:attribute>
          </xsl:if>
        </xs:param>
      </xsl:for-each>
      <!-- global variable, to make things easier -->
      <xs:variable name="apos">
        <xs:text>'</xs:text>
      </xs:variable>
      <xsl:apply-templates select="//defineTemplate | document(//include/@href)//defineTemplate" mode="process" />
      <xs:template match="/">
        <xsl:apply-templates select="content/* | *[not(self::content)]" />
        <xsl:choose>
          <xsl:when test="false() and content/*">
            <!-- look for a root node to start at, take the last -->
            <xsl:apply-templates select="content/*[position()=last()]" />
          </xsl:when>
          <xsl:otherwise>
            <!-- look for a named template to start at -->
            <!--xs:call-template name="root" /-->
          </xsl:otherwise>
          <!-- -->
        </xsl:choose>
      </xs:template>
      <!-- define a template that dumps the path to the context -->
      <xs:template name="callStack">
        <xs:param name="context" />
        <xs:if test="$context/..">
          <xs:call-template name="callStack">
            <xs:with-param name="context" select="$context/.." />
          </xs:call-template>
          <xs:text>/</xs:text>
        </xs:if>
        <xs:choose>
          <xs:when test="$context/../@*[generate-id(.)=generate-id($context)]">
            <xs:value-of select="'@'" />
            <xs:value-of select="name($context)" />
          </xs:when>
          <xs:otherwise>
            <xs:value-of select="name($context)" />
            <xs:if test="count($context/@*) &gt; 0">
              <xs:text>[</xs:text>
              <xs:for-each select="$context/@*">
                <xs:value-of select="concat('@',name(),'=',$apos,.,$apos)" disable-output-escaping="yes"/>
                <xs:if test="not(last())"> and </xs:if>
              </xs:for-each>
              <xs:text>]</xs:text>
            </xs:if>
          </xs:otherwise>
        </xs:choose>
      </xs:template>
    </xs:stylesheet>
  </xsl:template>

  <xsl:template name="process">
    <xsl:param name="data" />

    <xsl:for-each select="$data">

      <xsl:choose>
        <xsl:when test="count(preceding-sibling::* | preceding-sibling::text()[normalize-space(.)!=''])=0">
          <!-- first node -->
          <xsl:choose>
            <!--xsl:when test="self::text() and count(preceding-sibling::*)=0 and count(following-sibling::*)=0"></xsl:when-->
            <xsl:when test="count(key('isstatic', generate-id(.)))=1 and count(key('isdynamic', generate-id( parent::* )))=1">
              <!--xsl:if test="not(self::text() and (count(following-sibling::* | following-sibling::text()[normalize-space(.)!=''])=0 or count(key('isdynamic', generate-id((following-sibling::* | following-sibling::text()[normalize-space(.)!=''])[1])))=1))"-->
              <!--<xsl:comment>begin1</xsl:comment>-->
              <xsl:choose>
                <xsl:when test="local-name(..)='text'">
                  <!--xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text-->
                </xsl:when>
                <xsl:otherwise>
                  <xsl:text disable-output-escaping="yes">&lt;xsl:text disable-output-escaping="yes"&gt;&lt;![CDATA[</xsl:text>
                </xsl:otherwise>
              </xsl:choose>
              <!--/xsl:if-->
            </xsl:when>
            <xsl:when test="count(key('isdynamic', generate-id(.)))=1 and count(key('isstatic', generate-id( parent::* )))=1">
              <!--<xsl:comment>end1</xsl:comment>-->
              <xsl:choose>
                <xsl:when test="local-name(..)='text'">
                  <!--xsl:text disable-output-escaping="yes">]]&gt;</xsl:text-->
                </xsl:when>
                <xsl:otherwise>
                  <xsl:text disable-output-escaping="yes">]]&gt;&lt;/xsl:text&gt;</xsl:text>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:when>
          </xsl:choose>
        </xsl:when>
        <xsl:otherwise>
          <xsl:choose>

            <xsl:when test="count(key('isstatic', generate-id(.)))=1 and count(key('isdynamic', generate-id( (preceding-sibling::* | preceding-sibling::text()[normalize-space(.)!=''])[last()] )))=1">
              <!--xsl:if test="not(self::text() and (count(following-sibling::* | following-sibling::text()[normalize-space(.)!=''])=0 or count(key('isdynamic', generate-id((following-sibling::* | following-sibling::text()[normalize-space(.)!=''])[1])))=1))"-->
              <!--<xsl:comment>begin2</xsl:comment>-->
              <xsl:choose>
                <xsl:when test="local-name(..)='text'">
                  <!--xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text-->
                </xsl:when>
                <xsl:otherwise>
                  <xsl:text disable-output-escaping="yes">&lt;xsl:text disable-output-escaping="yes"&gt;&lt;![CDATA[</xsl:text>
                </xsl:otherwise>
              </xsl:choose>

              <!--/xsl:if-->
            </xsl:when>
            <xsl:when test="count(key('isdynamic', generate-id(.)))=1 and count(key('isstatic', generate-id( (preceding-sibling::* | preceding-sibling::text()[normalize-space(.)!=''])[last()] )))=1">
              <!--<xsl:comment>end2</xsl:comment>-->
              <xsl:choose>
                <xsl:when test="local-name(..)='text'">
                  <!--xsl:text disable-output-escaping="yes">]]&gt;</xsl:text-->
                </xsl:when>
                <xsl:otherwise>
                  <xsl:text disable-output-escaping="yes">]]&gt;&lt;/xsl:text&gt;</xsl:text>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:when>
          </xsl:choose>
        </xsl:otherwise>
      </xsl:choose>

      <xsl:choose>
        <xsl:when test="parent::* and local-name(.)='' and normalize-space(.)!=''">
          <xsl:copy-of select="normalize-space(.)" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:copy>
            <xsl:copy-of select="@*" />
            <xsl:call-template name="process">
              <xsl:with-param name="data" select="* | text()[normalize-space(.)!='']" />
            </xsl:call-template>
          </xsl:copy>
        </xsl:otherwise>
      </xsl:choose>

      <xsl:choose>
        <xsl:when test="count(following-sibling::* | following-sibling::text()[normalize-space(.)!=''])=0">
          <!-- last node -->
          <xsl:choose>
            <!--xsl:when test="self::text()"></xsl:when-->
            <xsl:when test="count(key('isstatic', generate-id(.)))=1 and count(key('isdynamic', generate-id( parent::* )))=1">
              <!--<xsl:comment>end3</xsl:comment>-->
              <xsl:choose>
                <xsl:when test="local-name(..)='text'">
                  <!--xsl:text disable-output-escaping="yes">]]&gt;</xsl:text-->
                </xsl:when>
                <xsl:otherwise>
                  <xsl:text disable-output-escaping="yes">]]&gt;&lt;/xsl:text&gt;</xsl:text>
                </xsl:otherwise>
              </xsl:choose>

            </xsl:when>
            <xsl:when test="count(key('isdynamic', generate-id(.)))=1 and count(key('isstatic', generate-id( parent::* )))=1">
              <!--<xsl:comment>begin3</xsl:comment>-->
              <xsl:choose>
                <xsl:when test="local-name(..)='text'">
                  <!--xsl:text disable-output-escaping="yes">&lt;![CDATA[</xsl:text-->
                </xsl:when>
                <xsl:otherwise>
                  <xsl:text disable-output-escaping="yes">&lt;xsl:text disable-output-escaping="yes"&gt;&lt;![CDATA[</xsl:text>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:when>
          </xsl:choose>
        </xsl:when>
      </xsl:choose>


    </xsl:for-each>




  </xsl:template>

  <!-- template:xhtml - catch all html elements and attributes -->
  <xsl:template match="@*" mode="decode">
    <xsl:choose>
      <xsl:when test="substring-before(.,'{{') or substring-after(.,'{{') or substring-before(.,'}}') or substring-after(.,'}}')">

        <!-- replace { with {{, {{ with {, } with }} and }} with } -->
        <xsl:call-template name="switchDoubleEncoding">
          <xsl:with-param name="text">
            <xsl:call-template name="switchDoubleEncoding">
              <xsl:with-param name="text" select="." />
              <xsl:with-param name="single" select="'}'" />
            </xsl:call-template>
          </xsl:with-param>
          <xsl:with-param name="single" select="'{'" />
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="substring-before(.,'{') or substring-after(.,'{') or substring-before(.,'}') or substring-after(.,'}')">
        <!-- replace { with {{ and } with }} -->
        <xsl:call-template name="replace">
          <xsl:with-param name="text">
            <xsl:call-template name="replace">
              <xsl:with-param name="text" select="." />
              <xsl:with-param name="find" select="'{'" />
              <xsl:with-param name="replace" select="'{{'" />
            </xsl:call-template>
          </xsl:with-param>
          <xsl:with-param name="find" select="'}'" />
          <xsl:with-param name="replace" select="'}}'" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="." />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="*">
    <xsl:choose>
      <xsl:when test="@condition and @forEach">
        <xsl:choose>
          <xsl:when test="generate-id(@condition) &lt; generate-id(@forEach)">
            <xs:if test="{@condition}">
              <xs:for-each select="{@forEach}">
                <xsl:apply-templates select="." mode="inner" />
              </xs:for-each>
            </xs:if>
          </xsl:when>
          <xsl:otherwise>
            <xs:for-each select="{@forEach}">
              <xs:if test="{@condition}">
                <xsl:apply-templates select="." mode="inner" />
              </xs:if>
            </xs:for-each>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:when test="@condition">
        <xs:if test="{@condition}">
          <xsl:apply-templates select="." mode="inner" />
        </xs:if>
      </xsl:when>
      <xsl:when test="@forEach">
        <xs:for-each select="{@forEach}">
          <xsl:apply-templates select="." mode="inner" />
        </xs:for-each>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="." mode="inner" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="*" mode="inner">
    <xsl:message>
      <xsl:value-of select="concat(namespace-uri(),':',name())"/>
    </xsl:message>
    <xsl:copy>
      <xsl:for-each select="@*[name() != 'forEach' and name() != 'condition']">
        <xsl:variable name="prefix">
          <xsl:value-of select="substring-before(name(),':') " />
        </xsl:variable>
        <xsl:choose>
          <xsl:when test="$prefix='eval'">
            <xs:attribute name="{substring-after(name(),':')}">
              <xs:value-of select="{.}" />
            </xs:attribute>
          </xsl:when>
          <xsl:otherwise>
            <xsl:attribute name="{name()}">
              <xsl:choose>
                <xsl:when test="substring-before(.,'{{') or substring-after(.,'{{') or substring-before(.,'}}') or substring-after(.,'}}')">
                  <!-- replace { with {{, {{ with {, } with }} and }} with } -->
                  <xsl:call-template name="switchDoubleEncoding">
                    <xsl:with-param name="text">
                      <xsl:call-template name="switchDoubleEncoding">
                        <xsl:with-param name="text" select="." />
                        <xsl:with-param name="single" select="'}'" />
                      </xsl:call-template>
                    </xsl:with-param>
                    <xsl:with-param name="single" select="'{'" />
                  </xsl:call-template>
                </xsl:when>
                <xsl:when test="substring-before(.,'{') or substring-after(.,'{') or substring-before(.,'}') or substring-after(.,'}')">
                  <!-- replace { with {{ and } with }} -->
                  <xsl:call-template name="replace">
                    <xsl:with-param name="text">
                      <xsl:call-template name="replace">
                        <xsl:with-param name="text" select="." />
                        <xsl:with-param name="find" select="'{'" />
                        <xsl:with-param name="replace" select="'{{'" />
                      </xsl:call-template>
                    </xsl:with-param>
                    <xsl:with-param name="find" select="'}'" />
                    <xsl:with-param name="replace" select="'}}'" />
                  </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="." />
                </xsl:otherwise>
              </xsl:choose>
            </xsl:attribute>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each>
      <xsl:apply-templates select="* | text() | comment()" />
      <xsl:if test="not(* | text() | comment()) ">
        <xsl:apply-templates select="." mode="empty" />
      </xsl:if>
    </xsl:copy>
  </xsl:template>


  <!-- template:actionLink element -->
  <!-- returns a route url or href if parent is an anchor tag, or action if parent is a form element -->

  <xsl:template match="actionLink" mode="inner">
    <xsl:choose>
      <xsl:when test="parent::a">
        <xs:attribute name="href">
          <xsl:apply-templates select="." mode="generate" />
        </xs:attribute>
      </xsl:when>
      <xsl:when test="parent::form">
        <xs:attribute name="action">
          <xsl:apply-templates select="." mode="generate" />
        </xs:attribute>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="." mode="generate" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- generate actionLink content -->
  <xsl:template match="actionLink" mode="generate">
    <!-- use unique id to distinguish local variables -->
    <xsl:variable name="uniqueID" select="generate-id(.)" />
    <xsl:if test="*">
      <xs:variable name="routeValues{$uniqueID}">
        <xsl:for-each select="*">
          <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="* | text() | comment()" />
          </xsl:copy>
        </xsl:for-each>
      </xs:variable>
    </xsl:if>
    <xs:variable name="action{$uniqueID}">
      <xsl:value-of select="@action" />
    </xs:variable>
    <xsl:choose>
      <xsl:when test="@controller">
        <xs:variable name="controller{$uniqueID}">
          <xsl:value-of select="@controller" />
        </xs:variable>
        <xsl:choose>
          <xsl:when test="*">
            <xs:value-of select="link:ActionLink($action{$uniqueID},$controller{$uniqueID},$routeValues{$uniqueID})" disable-output-escaping="yes" />
          </xsl:when>
          <xsl:otherwise>
            <xs:value-of select="link:ActionLink($action{$uniqueID},$controller{$uniqueID})" disable-output-escaping="yes" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:when test="*">
        <xs:value-of select="link:ActionLink($action{$uniqueID},$routeValues{$uniqueID})" disable-output-escaping="yes" />
      </xsl:when>
      <xsl:otherwise>
        <xs:value-of select="link:ActionLink($action{$uniqueID})" disable-output-escaping="yes" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="ajaxOptions" mode="inner">
    <xs:variable name="ajaxOptions">
      <xsl:for-each select="*">
        <xsl:copy>
          <xsl:copy-of select="@*"/>
          <xsl:apply-templates select="* | text() | comment()" />
        </xsl:copy>
      </xsl:for-each>
    </xs:variable>
    <xsl:choose>
      <xsl:when test="parent::a | parent::select">
        <xs:attribute name="onclick">
          <xs:value-of select="{concat('ajax:AjaxLink(','$ajaxOptions)')}" disable-output-escaping="yes" />
        </xs:attribute>
      </xsl:when>
      <xsl:when test="parent::form">
        <!--xs:attribute name="onsubmit">
          <xs:text>Sys.Mvc.AsyncForm.handleSubmit(this, new Sys.UI.DomEvent(event), </xs:text>
          <xs:text>{</xs:text>
          <xsl:for-each select="*">
            <xs:variable name="{name()}Value">
              <xsl:apply-templates select="* | text() | comment()" />
            </xs:variable>
            <xsl:choose>
              <xsl:when test="name()='InsertionMode'">
                <xs:text>insertionMode: Sys.Mvc.InsertionMode.</xs:text>
                <xs:value-of select="lower(${name()}Value)" />
              </xsl:when>
              <xsl:when test="name()='UpdateTargetId'">
                <xs:text>updateTargetId:'</xs:text>
                <xs:value-of select="${name()}Value" />
                <xs:text>'</xs:text>
              </xsl:when>
              <xsl:when test="name()='OnSuccess'">
                <xs:text>onSuccess:Function.createDelegate(this, </xs:text>
                <xs:value-of select="${name()}Value" />
                <xs:text>)</xs:text>
              </xsl:when>
              <xsl:when test="name()='OnBegin'">
                <xs:text>onBegin:Function.createDelegate(this, </xs:text>
                <xs:value-of select="${name()}Value" />
                <xs:text>)</xs:text>
              </xsl:when>
              <xsl:when test="name()='OnComplete'">
                <xs:text>onComplete:Function.createDelegate(this, </xs:text>
                <xs:value-of select="${name()}Value" />
                <xs:text>)</xs:text>
              </xsl:when>
            </xsl:choose>
            <xsl:if test="position()!=last()">,</xsl:if>
          </xsl:for-each>
          <xs:text>}</xs:text>
          <xs:text>);</xs:text>
        </xs:attribute-->
        <xs:attribute name="onsubmit">
          <xs:value-of select="{concat('ajax:AjaxSubmit(','$ajaxOptions)')}" disable-output-escaping="yes" />
        </xs:attribute>
        <xs:attribute name="onclick">Sys.Mvc.AsyncForm.handleClick(this, new Sys.UI.DomEvent(event));</xs:attribute>
      </xsl:when>
      <xsl:otherwise>
        <xs:value-of select="{concat('ajax:AjaxLink(','$ajaxOptions)')}" disable-output-escaping="yes" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- template:assert -->
  <xsl:template match="assert" mode="inner">
    <xs:if test="not({@test})">
      <xs:message terminate="yes">
        <xsl:choose>
          <xsl:when test="@message">
            <xsl:value-of select="@message" />
          </xsl:when>
          <xsl:otherwise>
            <xs:text>
              Assert '<xsl:value-of select="@test"/>' failed at
            </xs:text>

            <xs:call-template name="callStack">
              <xs:with-param name="context" select="." />
            </xs:call-template>.
          </xsl:otherwise>
        </xsl:choose>
      </xs:message>
    </xs:if>
  </xsl:template>

  <xsl:template match="attribute" mode="inner">
    <xs:attribute name="{@name}">
      <xsl:apply-templates select="* | text() | comment()" />
    </xs:attribute>
  </xsl:template>

  <!-- wrap content with a cdata section -->
  <xsl:template match="cdata">
    <xs:text disable-output-escaping="yes">&lt;![CDATA[</xs:text>
    <xsl:apply-templates select="*" />
    <xs:text disable-output-escaping="yes">]]&gt;</xs:text>
  </xsl:template>

  <xsl:template match="comment">
    <xs:comment>
      <xsl:apply-templates select="*" />
    </xs:comment>
  </xsl:template>
  <!-- content tags are used to contain other content, but are ignored themselves -->
  <xsl:template match="content">
    <xsl:apply-templates select="* | text() | comment()" />
  </xsl:template>

  <xsl:template match="comment()">
    <xsl:choose>
      <xsl:when test="parent::*[name()='script' or name()='style']">
        <xsl:choose>
          <xsl:when test="starts-with(/*/@doctype, 'xhtml')">
            <xs:text disable-output-escaping="yes">//&lt;![CDATA[</xs:text>
            <xsl:value-of select="." />
            <xs:text disable-output-escaping="yes">//]]&gt;</xs:text>
          </xsl:when>
          <xsl:otherwise>
            <xs:comment>
              <xsl:value-of select="." />
            </xs:comment>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:otherwise>
        <!--xs:comment>
          <xsl:value-of select="local-name(parent::*)"/>
          <xsl:value-of select="." />
        </xs:comment-->
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <xsl:template match="copyOf">
    <xsl:apply-imports />
    <xs:copy-of select="{@select}" />
  </xsl:template>

  <xsl:template match="debug">
    <!-- put debug execution here -->
    <!--xsl:value-of select="count(//defineTemplate | document(//include/@href)//defineTemplate)" /-->

    <xs:copy-of select="/" />
  </xsl:template>

  <xsl:template match="*[namespace-uri(.)='http://www.w3.org/1999/XSL/Transform']">
    <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:apply-templates select="*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="defineTemplate" mode="inner" />
  <xsl:template match="defineTemplate" mode="process">
    <xs:template>
      <xsl:choose>
        <xsl:when test="@match">
          <xsl:attribute name="match">
            <xsl:value-of select="@match" />
          </xsl:attribute>
          <xsl:if test="@mode">
            <xsl:attribute name="mode">
              <xsl:value-of select="@mode" />
            </xsl:attribute>
          </xsl:if>
        </xsl:when>
        <xsl:when test="@name">
          <xsl:attribute name="name">
            <xsl:value-of select="@name" />
          </xsl:attribute>
        </xsl:when>
      </xsl:choose>
      <xsl:apply-templates select="* | text() | comment()" />
    </xs:template>
  </xsl:template>

  <!-- template:forEach element -->
  <xsl:template match="forEach" mode="inner">
    <xs:for-each select="{@select}">
      <xsl:apply-templates select="* | text() | comment()" />
    </xs:for-each>
  </xsl:template>

  <xsl:template match="form">
    <xs:variable name="form" select="form:BeginForm(., '{@id}')" />
    <xsl:apply-templates select="." mode="inner" />
    <xs:value-of select="form:EndForm($form)" disable-output-escaping="yes" />
  </xsl:template>

  <!--
  <xsl:template match="formAction">
    <xs:variable name="action">
      <xsl:value-of select="@action" />
    </xs:variable>
    <xsl:choose>
      <xsl:when test="*">
        <xs:variable name="routeValues">
          <xsl:for-each select="*">
            <xsl:copy>
              <xsl:copy-of select="@*"/>
              <xsl:apply-templates select="* | text()" />
            </xsl:copy>
          </xsl:for-each>
        </xs:variable>
        <xsl:choose>
          <xsl:when test="parent::form">
            <xs:attribute name="action">
              <xs:value-of select="form:ActionLink($action,$routeValues)" />
            </xs:attribute>
          </xsl:when>
          <xsl:otherwise>
            <xs:value-of select="form:ActionLink($action,$routeValues)" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:otherwise>
        <xsl:choose>
          <xsl:when test="parent::form">
            <xs:attribute name="action">
              <xs:value-of select="form:ActionLink({@action})" />
            </xs:attribute>
          </xsl:when>
          <xsl:otherwise>
            <xs:value-of select="form:ActionLink({@action})" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  -->

  <xsl:template match="import">
    <xs:import href="{@href}" />
  </xsl:template>

  <!-- template:if element -->
  <xsl:template match="if" mode="inner">
    <xs:if test="{@test}">
      <xsl:apply-templates select="* | text() | comment()" />
    </xs:if>
  </xsl:template>

  <xsl:template match="include" mode="inner">
    <xsl:choose>
      <xsl:when test="@preProcess='true'">
        <xsl:apply-templates select="document(concat(@href,'?p=1'))/root/text()" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:for-each select="document(@href)/content">
          <xsl:apply-templates />
        </xsl:for-each>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="param[not(parent::defineTemplate)]" />
  
  <xsl:template match="param[parent::defineTemplate]">
    <xs:param name="{@name}">
      <xsl:if test="@select">
        <xsl:attribute name="select">
          <xsl:value-of select="@select"/>
        </xsl:attribute>
      </xsl:if>
      <xsl:apply-templates />
    </xs:param>
  </xsl:template>

  <xsl:template match="renderAction" mode="inner">
    <!-- use unique id to distinguish local variables -->
    <xsl:variable name="uniqueID" select="generate-id(.)" />
    <xsl:if test="*">
      <xs:variable name="routeValues{$uniqueID}">
        <xsl:for-each select="*">
          <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="* | text() | comment()" />
          </xsl:copy>
        </xsl:for-each>
      </xs:variable>
    </xsl:if>
    <xs:variable name="action{$uniqueID}">
      <xsl:value-of select="@action" />
    </xs:variable>
    <xsl:choose>
      <xsl:when test="@controller">
        <xs:variable name="controller{$uniqueID}">
          <xsl:value-of select="@controller" />
        </xs:variable>
        <xsl:choose>
          <xsl:when test="*">
            <xs:value-of select="childAction:Action($action{$uniqueID},$controller{$uniqueID},$routeValues{$uniqueID})" disable-output-escaping="yes" />
          </xsl:when>
          <xsl:otherwise>
            <xs:value-of select="childAction:Action($action{$uniqueID},$controller{$uniqueID})" disable-output-escaping="yes" />
          </xsl:otherwise>
        </xsl:choose>
      </xsl:when>
      <xsl:when test="*">
        <xs:value-of select="childAction:Action($action{$uniqueID},$routeValues{$uniqueID})" disable-output-escaping="yes" />
      </xsl:when>
      <xsl:otherwise>
        <xs:value-of select="childAction:Action($action{$uniqueID})" disable-output-escaping="yes" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- template:renderPartial -->
  <xsl:template match="renderPartial" mode="inner">
    <xs:value-of select="{concat('renderPartial:RenderPartial(',@viewName,')')}" disable-output-escaping="yes" />
  </xsl:template>

  <xsl:template match="renderTemplate">
    <xs:call-template name="{@name}">
      <xsl:for-each select="@*">
        <xs:with-param name="{name()}" select="{.}" />
      </xsl:for-each>
      <xsl:for-each select="*">
        <xs:with-param name="{name()}">
          <xsl:apply-templates select="*" />
        </xs:with-param>
      </xsl:for-each>
    </xs:call-template>
  </xsl:template>

  <xsl:template match="renderTemplates">
    <xs:apply-templates select="{@select}">
      <xsl:if test="@mode">
        <xsl:attribute name="mode">
          <xsl:value-of select="@mode" />
        </xsl:attribute>
      </xsl:if>
    </xs:apply-templates>
  </xsl:template>

  <xsl:template match="resourceString">
    <xsl:call-template name="resourceString">
      <xsl:with-param name="name" select="@name" />
    </xsl:call-template>
  </xsl:template>

  <!-- templates -->
  <xsl:template name="resourceString">
    <xsl:param name="name" />
    <xsl:for-each select="$resources[1]">
      <xsl:value-of select="key('resource_key', $name)" />
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="script" mode="empty">
    <xsl:text>//</xsl:text>
  </xsl:template>

  <xsl:template match="setting">
    <xsl:choose>
      <xsl:when test="@enableClientValidation='true'">
        <xs:variable name="test" select="mvc:EnableClientValidation()" />
      </xsl:when>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="template">
    <xsl:choose>
      <xsl:when test="@name">
        <xs:template name="{@name}">
          <xsl:apply-templates select="*" />
        </xs:template>
      </xsl:when>
      <xsl:when test="@match">
        <xs:template match="{@match}">
          <xsl:apply-templates select="*" />
        </xs:template>
      </xsl:when>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="text" mode="inner">
    <xsl:variable name="key" select="@key" />
    <xsl:variable name="content" select="* | text() | comment()" />
    <xsl:for-each select="$resources[1]">
      <xsl:choose>
        <xsl:when test="key('resource_key', $key)">
          <xsl:value-of select="key('resource_key', $key)" disable-output-escaping="yes" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:apply-templates select="$content" />
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="text()">
    <xsl:copy />
  </xsl:template>

  <xsl:template match="text()[parent::*[@disable-output-escaping='yes']]">
    <xs:text disable-output-escaping="yes">
      <xsl:value-of select="." />
    </xs:text>
  </xsl:template>

  <xsl:template match="validationMessage" mode="inner">
    <xsl:if test="*">
      <xs:variable name="routeValues">
        <xsl:for-each select="*">
          <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="* | text() | comment()" />
          </xsl:copy>
        </xsl:for-each>
      </xs:variable>
    </xsl:if>
    <xs:variable name="modelName{generate-id(.)}">
      <xsl:value-of select="@modelName" />
    </xs:variable>
    <xs:value-of select="validation:ValidationMessage($modelName{generate-id(.)})" disable-output-escaping="yes" />
  </xsl:template>

  <xsl:template match="validationSummary" mode="inner">
    <xs:value-of select="validation:ValidationSummary()" disable-output-escaping="yes" />
  </xsl:template>

  <xsl:template match="validationCaptcha" mode="inner">
    <xs:value-of select="validation:GenerateCaptcha()" disable-output-escaping="yes" />
  </xsl:template>

  <!-- template:valueOf -->
  <xsl:template match="valueOf" mode="inner">
    <xsl:if test="not(@select)">
      <xsl:message terminate="yes">select attribute is required</xsl:message>
    </xsl:if>
    <xs:value-of>
      <xsl:attribute name="select">
        <xsl:apply-templates select="@select" />
      </xsl:attribute>
      <xsl:if test="@disable-output-escaping">
        <xsl:attribute name="disable-output-escaping">
          <xsl:apply-templates select="@disable-output-escaping" />
        </xsl:attribute>
      </xsl:if>
    </xs:value-of>
  </xsl:template>

  <xsl:template match="variable">
    <xs:variable name="{@name}">
      <xsl:if test="@select">
        <xsl:attribute name="select">
          <xsl:value-of select="@select"/>
        </xsl:attribute>
      </xsl:if>
      <xsl:apply-templates />
    </xs:variable>
  </xsl:template>

  <!-- function:switchDoubleEncoding - switches escaped character sequences, eg. { with {{ and {{ with { -->
  <xsl:template name="switchDoubleEncoding">
    <xsl:param name="text" />
    <xsl:param name="single" />
    <xsl:param name="double" select="concat($single, $single)" />
    <xsl:variable name="before1" select="substring-before($text, $single)" />
    <xsl:variable name="after1" select="substring-after($text, $single)" />
    <xsl:variable name="before2" select="substring-before($text, $double)" />
    <xsl:variable name="after2" select="substring-after($text, $double)" />
    <xsl:choose>
      <xsl:when test="($before2 != '' or $after2 != '') and (($before1 = '' and $after1 = '') or (string-length($before2) &lt;= string-length($before1)))">
        <xsl:value-of select="$before2"/>
        <xsl:value-of select="$single" />
        <xsl:call-template name="switchDoubleEncoding">
          <xsl:with-param name="text" select="$after2" />
          <xsl:with-param name="single" select="$single" />
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="($before1 != '' or $after1 != '') and (($before2 = '' and $after2 = '') or (string-length($before1) &lt;= string-length($before2)))">
        <xsl:value-of select="$before1"/>
        <xsl:value-of select="$double" />
        <xsl:call-template name="switchDoubleEncoding">
          <xsl:with-param name="text" select="$after1" />
          <xsl:with-param name="single" select="$single" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- function:replace - find and replace -->
  <xsl:template name="replace">
    <xsl:param name="text" />
    <xsl:param name="find" />
    <xsl:param name="replace" />
    <xsl:variable name="before" select="substring-before($text, $find)" />
    <xsl:variable name="after" select="substring-after($text, $find)" />
    <xsl:choose>
      <xsl:when test="$after != '' or $before != ''">
        <xsl:value-of select="$before" />
        <xsl:value-of select="$replace" />
        <xsl:call-template name="replace">
          <xsl:with-param name="text" select="$after" />
          <xsl:with-param name="find" select="$find" />
          <xsl:with-param name="replace" select="$replace" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- template:escape - escapes single quotes -->
  <xsl:template name="escape">
    <xsl:param name="text"/>
    <xsl:choose>
      <xsl:when test="substring-after($text,$apos) != ''">
        <xsl:value-of select="substring-before($text,$apos)" />
        <xsl:value-of select="concat($apos,',$apos,',$apos)" disable-output-escaping="no"/>
        <xsl:call-template name="escape">
          <xsl:with-param name="text" select="substring-after($text,$apos)" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>
